/*
  FileName : GPS.c
  Description :
  Created on 2008.11.21 by ZZP.

  Revision History:
		本应用中 GPS 位置的判断只适用于北半球、东经范围，其他范围则需要修改。

		2013.7.15: 根据《（20130607）关于CIR与LBJ功能优化的补充技术规范》要求，更改GPS相关数据库及逻辑。
		    1、关联站增加到8个；前站也增加到8个；
			2、相邻站增加到15个；（对于有联络线联通某两个站，但数据库里没有直接通达的情况，在生成数据库时，
									可搜索GPS位置，如果很近则设置为邻站，这样，即使没有直达，亦可找到----
									限制：只适用于车站，不包括信息点，且不能包括为区分距离很近的两条线路而设置的
									同样经纬度的两个站）
			3、区域中的线路增加到7个；
			4、包含不同线路的车站，设置多个经纬度相同的车站以区分其线路；
			5、转换点可以包含在车站内；
			6、强制选择线路及其退出机制；
			7、任意时刻司机选择线路都有响应：在区域内则传区域；站内传送当前站的关联线路；在区间则传当前线路；
*/
#include <std.h>
#include <hwi.h>//此头文件有 HWI_ 系列定义
#include "MxxTimer.h"
#include "X_Uart.h"
#include "UartData.h"
#include "DSP281x_GlobalPrototypes.h"
#include "XFlash.h"
#include "GPS_Location_Handle.h"
#include "CirGpsCommand.h"
#include "GPS_Region.h"
#include "GPS_Multiply_By.h"
#include "GPS_MMITransmitdata.h"


extern DATA_BASE_INFO DataBase;

//----------------------------------------
#ifdef __cplusplus
#pragma DATA_SECTION("UserDataFile")
#else
#pragma DATA_SECTION(MMIData,"UserDataFile");
#endif
INQUIRY_MMI_DATA MMIData[MMI_BUF_MASK + 1];

volatile Uns MMIIndex = 0;
volatile Uns MMIHandleIndex = 0;




////////////////////////////////////////////////////////////////////////////////
//                        USART Data to MMI
////////////////////////////////////////////////////////////////////////////////
//initialize the MMIData[MMIIndex]
void InitCurrMMIData(void)
{
	Uns i;

	i = MMIIndex;
	MMIData[i].SrcID = 0x06;
	MMIData[i].SrcLen = 0;
	MMIData[i].DestID = 0x02;
	MMIData[i].DestLen = 0;
	MMIData[i].Type = 0x02;
}


//According to command to prepare MMIData
Uns ToMMIData(Uns Cmd)
{
	Uns i;

	InitCurrMMIData();
	switch (Cmd)
	{
	case Tx_Cmd_GPS_ExitRegion:
		MMIData[MMIIndex].Cmd = Cmd;
		MMIData[MMIIndex].DataLenLo = 0 + 8;
		MMIData[MMIIndex].DataLenHi = 0;

		IncIndex((Uns *)&MMIIndex, MMI_BUF_MASK);
		break;
	case Tx_Cmd_GPS_EnterAbs:
		MMIData[MMIIndex].Cmd = Cmd;
		i = 1 * 31 + 8;
		MMIData[MMIIndex].DataLenLo = i & 0xff;
		MMIData[MMIIndex].DataLenHi = i >> 8;
		//current road
		if(MyInfo.RoadLocked)
		{
			LineNameToMMIData(0,MyInfo.LockedRoadIndex);
		}

		IncIndex((Uns *)&MMIIndex, MMI_BUF_MASK);
		break;
	case Tx_Cmd_GPS_ExitAbs:
		MMIData[MMIIndex].Cmd = Cmd;
		i = 1 * 31 + 8;
		MMIData[MMIIndex].DataLenLo = i & 0xff;
		MMIData[MMIIndex].DataLenHi = i >> 8;
		//current road
		if(MyInfo.RoadLocked)
		{
			LineNameToMMIData(0,MyInfo.LockedRoadIndex);
		}

		IncIndex((Uns *)&MMIIndex, MMI_BUF_MASK);
		break;
	case Tx_Cmd_GPS_InqueryRoad:
		MMIData[MMIIndex].Cmd = Cmd;
		MMIData[MMIIndex].DataLenLo = 0 + 8;
		MMIData[MMIIndex].DataLenHi = 0;
		IncIndex((Uns *)&MMIIndex, MMI_BUF_MASK);
		break;
	default:
		break;
	}

	return 1;
}


//prepare MMIData for entering a new region
//Write MMIData
#pragma CODE_SECTION(ToMMIData_Region, "FuncsMap2H0SARam")
void ToMMIData_Region(REGION_INFO *	region_buf)
{
	Uns roadindex[8],roadcount=0,j;
	for(j=0;j<8 && region_buf->Rd_Index[j];j++)
	{
		//Calculate the number of road available which should not be bigger than 8.
		roadindex[roadcount]=region_buf->Rd_Index[j];
		roadcount++;
	}
	ToMMI_RoadSelection(Tx_Cmd_GPS_SelectRoad,roadindex,roadcount);
}


//According to command to prepare MMIData
void ToMMI_RoadSelection(Uns cmd,Uns *roadindex,Uns roadcount)
{
	Uns j,len;

	if(!roadcount)
		return;
	MMIData[MMIIndex].Cmd = cmd;					//UartData command
	len=roadcount*31+8;								//31 is the length of each road data
	MMIData[MMIIndex].DataLenLo = len & 0xff;
	MMIData[MMIIndex].DataLenHi = len >> 8;			//UartData length

	for (j = 0; j < roadcount; j++)
	{
		LineNameToMMIData(j,roadindex[j]);
	}

	MMIData[MMIIndex].SrcID		= 0x06;		//UartData data structure
	MMIData[MMIIndex].SrcLen	= 0;		//UartData data structure
	MMIData[MMIIndex].DestID	= 0x02;		//UartData data structure
	MMIData[MMIIndex].DestLen	= 0;		//UartData data structure
	MMIData[MMIIndex].Type		= 0x02;		//UartData data structure
	IncIndex((Uns *)&MMIIndex, MMI_BUF_MASK);
	return;
}

//put MMIData into port(GsmrPortInfo and PubPortInfo) transmit structure.
//not changing MMIData, but increase MMIHandleIndex.
//Called by Timing Function every 10ms.
Uns GPS_MMIDataHandler(void)
{
	Uns Len;

	if (MMIHandleIndex != MMIIndex)
	{
		Len = MMIData[MMIHandleIndex].DataLenLo + (MMIData[MMIHandleIndex].DataLenHi << 8);
		PrepareUartData((UART_PORT_INFO *)&GsmrPortInfo,
                      	(UART_PORT_INFO *)&PubPortInfo,
                      	(Uns *)&(MMIData[MMIHandleIndex]),
                      	Len + 2,
                      	8,
                      	0);//此为16位数据
		IncIndex((Uns *)&MMIHandleIndex, MMI_BUF_MASK);
		return 1;
	}
	return 0;
}

//put line information into Array MMIData[MMIIndex].RdData
//the first parameter is the index of Array RdName, start with 0
//the second parameter is the index of line in road DataBase.
//Called by GPSDataHandler task only
void LineNameToMMIData(Uns RdDataindex,Uns roadindex)
{
	Uns *P;
	Uns rd_info[15],i;

	P=&(MMIData[MMIIndex].RdData[RdDataindex].RdName[0]);
	S29G_FlashRead(rd_info,MyInfo.DBRoadOffset+1+roadindex*32-32,15);
	for (i = 0; i < 14; i++)//16-bit data to 8-bit data
	{
		*P++ = (rd_info[i] & 0xff);
		*P++ = (rd_info[i] >> 8);
	}
	MMIData[MMIIndex].RdData[RdDataindex].DispName[20] = rd_info[14] & 0xFF;
	MMIData[MMIIndex].RdData[RdDataindex].Mode = rd_info[14] >> 8;
	MMIData[MMIIndex].RdData[RdDataindex].Semicolon = ';';//UartData semicolon
}



//initialize the whole MMIData[]
void InitAllMMIData(void)
{
	Uns i;
	for (i = 0; i < MMI_BUF_MASK; i++)
	 {
		MMIData[i].SrcID = 0x06;
		MMIData[i].SrcLen = 0;
		MMIData[i].DestID = 0x02;
		MMIData[i].DestLen = 0;
		MMIData[i].Type = 0x02;
	}
}



